//
// Created by mio on 25-4-17.
//


#include "RtmpHandshake.h"

#include <cstring>
#include <random>


RtmpHandshake::RtmpHandshake(State state)
{
    handshake_state_ = state;
}

RtmpHandshake::~RtmpHandshake()
{
}

int RtmpHandshake::Parse(BufferReader& in_buffer, char* res_buf, uint32_t res_buf_size)
{
    // 获取输入缓冲区可读数据的指针和大小
    uint8_t* buf = (uint8_t*)in_buffer.Peek();
    uint32_t buf_size = in_buffer.ReadableBytes();
    uint32_t pos = 0;        // 已消费字节
    uint32_t res_size = 0;   // 生成的回复包长度
    std::random_device rd;   // 用于生成随机数 (C1/S1)

    /** ---------------- 客户端场景：收到 S0S1S2，需要回 C2 ---------------- */
    if (handshake_state_ == HANDSHAKE_S0S1S2) // 由客户端处理
    {
        if (buf_size < (1 + 1536 + 1536)) return res_size;
        if (buf[0] != 3) return -1;         // 版本不匹配，握手失败

        pos += 1 + 1536 + 1536;             // 接收 S0S1S2 成功
        // C2 是 S1 的一个副本
        res_size = 1536;                    // C2 的大小为 1536
        /* 构造 C2：规范要求将 S1 原样返回 */
        memcpy(res_buf, buf + 1, 1536);
        handshake_state_ = HANDSHAKE_COMPLETE; // 握手完成 (客户端视角)
    }
    /** ---------------- 服务器场景：收到 C0C1，需要回 S0S1S2 ------------- */
    else if (handshake_state_ == HANDSHAKE_C0C1)
    {
        if (buf_size < 1 + 1536) return res_size;
        else
        {
            if (buf[0] != 3) return -1;     // 检查客户端发送的 C0 版本号是否为 3
        }
        pos += 1537;                        // 接收 C0C1 成功, 标记消耗了 C0C1 的所有字节
        // ---------- 组包 S0S1S2 ----------
        res_size = 1 + 1536 + 1536;
        memset(res_buf, 0, res_size);
        res_buf[0] = 3;                     // S0：版本号

        char* p = res_buf;
        // 填充 S1：时间戳(4) + 版本(4) + 随机(1528)
        // 前 8 字节已置 0，这里只写随机 1528 字节
        p += 9;
        for (int i = 0; i < 1528; i++)      // 填充 1528 字节的随机数据
        {
            *p++ = rd();
        }

        // S2 = C1 直接复制 C1（不含 C0）
        memcpy(p, buf + 1, 1536);
        // 服务器状态转移到等待 C2
        handshake_state_ = HANDSHAKE_C2;
    }
    // 状态：服务器等待 C2
    else if (handshake_state_ == HANDSHAKE_C2) // 服务器处理C2
    {
        if (buf_size < 1536) // C2不完整
        {
            return res_size;
        }
        else
        {
            // C2 不需要检查内容，只需接收即可
            pos += 1536;
            // 接收 C2 后服务器握手完成，不需要再发送响应
            handshake_state_ = HANDSHAKE_COMPLETE;
        }
    }
    in_buffer.Retrieve(pos);
    return res_size;                         // 0 表示未产生回复包
}

int RtmpHandshake::BuildC0C1(char* buf, uint32_t buf_size) // 客户端需要创建C0C1
{
    uint32_t size = 1 + 1536;           // C0C1
    memset(buf, 0, size);
    buf[0] = 3;                         // 版本为3

    // C1：前 8 字节为时间戳和版本，这里简单置 0；后 1528 字节随机
    std::random_device rd;
    uint8_t* p = (uint8_t*) buf;
    p += 9;                             // 跳过 1+8 字节

    for (int i = 0; i < 1528; i++)      // 填充 1528 字节随机数据
    {
        *p++ = rd();
    }

    return size;                        // 返回生成的 C0C1 报文大小
}
